package com.cwx.mychat.utils.jwt;


import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.jsonwebtoken.*;
import io.jsonwebtoken.security.SecureDigestAlgorithm;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.util.Date;
import java.util.UUID;

public class JwtUtils {

    //有效期为
    public static final Long JWT_TTL = 60 * 60 * 24 * 365 *1000L;  //一年
    //设置秘钥明文
    /**
     * 私钥 / 生成签名的时候使用的秘钥secret，一般可以从本地配置文件中读取，切记这个秘钥不能外露，只在服务端使用，在任何场景都不应该流露出去。
     * 一旦客户端得知这个secret, 那就意味着客户端是可以自我签发jwt了。
     * 应该大于等于 256位(长度32及以上的字符串)，并且是随机的字符串
     */
    private final static String SECRET = "cwxwerwefzxcdsfawwwdawddadfasdasczxczsdasdad";
    /**
     * 加密算法
     */
    private final static SecureDigestAlgorithm<SecretKey, SecretKey> ALGORITHM = Jwts.SIG.HS256;
    /**
     * 秘钥实例
     */
//    public static final SecretKey KEY = Jwts.SIG.HS256.key().random(new SecureRandom(SECRET.getBytes(StandardCharsets.UTF_8))).build();
    public static final SecretKey KEY = new SecretKeySpec(SECRET.getBytes(StandardCharsets.UTF_8), SignatureAlgorithm.HS256.getJcaName());


    public static String getUUID(){
        return UUID.randomUUID().toString().replaceAll("-", "");
    }

    /**
     * 生成jtw
     * @param subject token中要存放的数据（json格式）
     * @return
     */
    public static String createJWT(String subject) {
        JwtBuilder builder = getJwtBuilder(subject, null, getUUID());// 设置过期时间
        return builder.compact();
    }

    /**
     * 生成jtw
     * @param subject token中要存放的数据（json格式）
     * @param ttlMillis token超时时间
     * @return
     */
    public static String createJWT(String subject, Long ttlMillis) {
        JwtBuilder builder = getJwtBuilder(subject, ttlMillis, getUUID());// 设置过期时间
        return builder.compact();
    }

    private static JwtBuilder getJwtBuilder(String subject, Long ttlMillis, String uuid) {
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);
        if(ttlMillis==null){
            ttlMillis=JwtUtils.JWT_TTL;
        }
        long expMillis = nowMillis + ttlMillis;
        Date expDate = new Date(expMillis);
        return Jwts.builder()
                .header()
                .add("type", "JWT")
                .add("alg", "HS256")
                .and()
                //设置自定义负载信息
                .claim("jwt", subject)
                //令牌ID
                .id(uuid)
                //过期时间
                .expiration(expDate)
                //签发时间
                .issuedAt(now)
                //主题 可以是JSON数据
                .subject(subject)
                //签发者
                .issuer("sg")
                //签名
                .signWith(KEY, ALGORITHM);
    }

    /**
     * 创建token
     * @param id
     * @param subject
     * @param ttlMillis
     * @return
     */
    public static String createJWT(String id, String subject, Long ttlMillis) {
        JwtBuilder builder = getJwtBuilder(subject, ttlMillis, id);// 设置过期时间
        return builder.compact();
    }


    /**
     * 解析
     *
     * @param jwt
     * @return
     * @throws Exception
     */
    public static Jws<Claims> parseJWT(String jwt) {
        return Jwts.parser()
                .verifyWith(KEY)
                .build()
                .parseSignedClaims(jwt);
    }
    /**
     * 验证jwt是否失效
     *
     * @param jwt
     * @return true:过期   false:没过期
     */
    public static boolean isExpired(String jwt) {
        try {
            final Date expiration = getExpiration(jwt);
            return expiration.before(new Date());
        } catch (ExpiredJwtException expiredJwtException) {
            return true;
        }
    }
    /**
     * 获取jwt失效时间
     */
    public static Date getExpiration(String jwt) {
        return parseJWT(jwt).getPayload().getExpiration();
    }


    public static void main(String[] args) throws JsonProcessingException {
        String southUrlJson = "{\"url\": \"http://10.19.28.145/dataex/_api/test?_url=getDeviceOpticalPower\",\"jsonHeader\": \"{\\\"a\\\":\\\"b\\\",\\\"c\\\":\\\"d\\\"}\",\"jsonParams\":\"{\\\"a\\\":\\\"b\\\",\\\"c\\\":\\\"d\\\"}\",\"beforeScript\": \"\",\"afterScript\": \"\"}";
        System.out.println(southUrlJson);
        ObjectMapper mapper = new ObjectMapper();
        JsonNode rootNode = mapper.readTree(southUrlJson);
        String southUrl = rootNode.get("url").asText();
        String jsonHeader = rootNode.get("jsonHeader").asText();
        String jsonParams = rootNode.get("jsonParams").asText();
        String beforeScript = rootNode.get("beforeScript").asText();
        String afterScript = rootNode.get("afterScript").asText();
        System.out.println(String.format("url = %s, jsonHeader = %s, jsonParams = %s, beforeScript = %s, afterScript = %s", southUrl, jsonHeader, jsonParams, beforeScript, afterScript));
    }
}
